//var StringUtil = com.tianji.www.shared.StringUtil;

var StringUtil = {
	entity:{
			"&": '&amp;',
			"<":  '&lt;',
			">":  '&gt;'
	},
	filterString:function(str){
		return String(str).replace(/[&|<|>]/g,
			function (a) {
			    return StringUtil.entity[a];
			}
		);
	}
}

var AdapterRegistry = function(/*Boolean?*/ returnWrappers){
	this.pairs = [];
	this.returnWrappers = returnWrappers || false; // Boolean
}
AdapterRegistry.prototype = {
	register: function(/*String*/ name, /*Function*/ check, /*Function*/ wrap, /*Boolean?*/ directReturn, /*Boolean?*/ override){
		this.pairs[((override) ? "unshift" : "push")]([name, check, wrap, directReturn]);
	},
	match: function(/* ... */){
		for(var i = 0; i < this.pairs.length; i++){
			var pair = this.pairs[i];
			if(pair[1].apply(this, arguments)){
				if((pair[3])||(this.returnWrappers)){
					return pair[2];
				}else{
					return pair[2].apply(this, arguments);
				}
			}
		}
		throw new Error("No match found");
	},
	unregister: function(name){
		for(var i = 0; i < this.pairs.length; i++){
			var pair = this.pairs[i];
			if(pair[0] == name){
				this.pairs.splice(i, 1);
				return true;
			}
		}
		return false;
	}
}
var handlers = new AdapterRegistry(true);

//0805,本来的想法是每次都需要判断一些额外的情况,因为我们从一个对象遍历的是所有的属性,所以可能遍历出一些一个对象系统的属性,或者方法,所以需要提供一个other的
//适配器,来处理这些额外的属性,但是昨天突然想到了为啥我不直接把这个对象的属性拿出来呢？为啥要把所有的都拿出来遍历呢？所以，下面就尝试这种方法,下面的other这个
//适配器就可能省略掉了啊
//还有一个问题就是我们的filter需要传递的参数有以下几种情况,然后可能需要不同的对待
//1.加入我们现在match了一个tjobject,然后我们需要遍历这个对象,然后再对对象内部属性进行处理,而这个对象所对应的属性name,对于我们来说没有什么用处了
//2.如果我们现在match了一个string,然后我们对这个字符串进行替换,然后再把这个过滤完成的字符串替换到原来的对象中。这个时候我们想要替换就需要三个参数了,
// 一个就是属性name,属性所在的bean,还有一个就是替换后的值,而且根据属性所在的对象替换又分为以下三种(1)如果是对象和map的话[]进行替换,如果是list的话，name就
//是对应的索引,list.set(index,value);map和对象比较类似。还有一个就是数组,也是比较类似可以bean[name(相当于索引)]进行替换，所以如何选择我们的替换方式，

// 就是新产生的另外一个问题,虽然我们的值都是字符串，但是由于他所在的位置(数组,list,obejct)不同，就会有不同的处理方式,目前的处理方式有两种,一种就是map和对象直接[],
// 处理另外一个就是list，他比较特殊,为了统一处理，我现在想到的方法就是在filter里面多加一个参数,就是替换处理函数，但是这个函数只有在替换字符串的时候才会调用，
// 当我们在处理到不是传统的属性替换方式的时候(比如list)我们就会把这个如何处理的过程传递进去,这样就进行了分离。所以我们可以定义两个默认的处理函数，
// 在不同的情况下进行使用。但是现在我们已知的替换方式就两种，所以我们先以最简单的方式来写，如果以后发现了更多情况的处理方式（应该不会有了吧！）然后再用更好的办法来实现。


//2.如果我们match了一个List,然后我们需要遍历这个list里面所有的对象,然后又分为两种情况(1)如果list里面的对象是对象,那么重复1，（2）如果是String的话，我们就需要
//原来的这个list对象，因为我们要对list里面的内容进行替换。
//3.如果我们match了一个map,然后我们需要遍历所有的values,然后也是类似分两种情况(1)如果value是对象,重复1,(2)如果是String的话,我们需要用原来的map进行替换,替换方式
//类似于对象
//所以现在我们为了统一接口,因为我们判断的逻辑想统一,因为我们match回来的时候，我们并不知道也不需要知道我们match的是哪一个类型的对象,所以我们需要把我们的最大参数传递
//进来。这样我们就可以根据我们具体类型的处理方法中进行处理，自己根据自己的类型，需要啥，拿啥
//现在就定义一下把filter(name,value,bean),但是value可以通过bean和name计算出来,先这样吧！如果有冗余的话，在处理,在明确一下这三个值的含义
//name是当前处理对象的属性name,value是当前处理的对象,bean代表这两个值所属于的对象

//下面的一个处理方式就是对于我们的checkout函数的处理了，目前我们的判断方式是根据把这个对象传递过来，然后我们通过判断这个对象是什么样的值，然后做相应的处理，本来是
//通过用string.indexOf这样来处理的，但是明显感觉不太好。所以准备修改为正则来判断 



//刚才又想到了另外一种处理方式,我们可以不可以这样,就是我们先收集到所有的字符串,然后根据字符串所在的位置(在对象中,在list中,在map中,在数组中)来构建出一个和替换方法进行
//绑定的对象,然后进行统一替换,那实际上就变成了,我们一直根据不同的条件,返回不同的替换对象,那我们的替换对象都找到了,为啥我们不就直接替换了呢?多次一举呀!好了,这是刚才临时
//想到的.

//好了,现在就根据上面的想法,对代码进行重新的整体,感觉昨天写的还是思路不是很清晰,写的基本上就是根据感觉走的,所以害的下午调试了一下午,就是因为有一点没有想清楚
//吸取的教训就是如果遇到一个感觉比较复杂的问题，一定要把思路整体清楚，然后再下笔写，尽量不要编写边想

//list中的字符串替换方式
var listRepl = function(name,value,bean){
	bean.set(name,StringUtil.filterString(value));
}

//obj,map,数组等方式字符串替换方式
var objRepl = function(name,value,bean){
	bean[name] = StringUtil.filterString(value);
}

handlers.register("other",function(value){
	//由于现在的对象不可能是函数，或者是class属性了,因为用了getgetDeclaredFields方法，所以下面的判断可以省略了
	//只需要判断是否为空就行了啊
	//var matched = !value || (typeof value !== 'object') || (getClassName(value) == 'java.lang.Class');
	return !value;
},{
	filter: function(){
		return;
	}
});

var matchReg = {
	obj:/(^com\.tianji)|(^leoner)/,
	list:/^java\.util\..*List$/,
	map:/^java\.util\..*Map$/,
	array:/^\[L.*/
}
handlers.register("object",function(value){
	var name = getClassName(value);
//	return name.indexOf("com.tianji") > -1 || name.indexOf("leoner") > -1;
	return matchReg.obj.test(name);
},{
	filter: function(name,value,bean){
		//传递进来name是属性的名称,value为属性对应的值,bean为name所属于的对象
		//专门查找对象的属性，通过这种优化，速度快了2/3，看来多了大量没有必要的判断，是挺影响速度的。
		var fields = value.getClass().getDeclaredFields();
		for(var index in fields){
			var field = fields[index];
			var new_value = value[field.getName()];		
			handlers.match(new_value).filter(field.getName(),new_value,value,objRepl);
		}
//		for(var attr in value){
//			var new_value = value[attr];
//			handlers.match(new_value).filter(attr,new_value,value,objRepl);
//		}
		return;
	}
});
handlers.register("string",function(value){
	 return (getClassName(value) == 'java.lang.String');
},{
	filter: function(name,value,bean,replHandler){
		replHandler.apply(this,arguments);
	}
});

handlers.register("list",function(value){
	var name = getClassName(value);
//	return name.indexOf("java.util") == 0 && name.indexOf("List") > 0;
	return matchReg.list.test(name);
},{
	filter: function(name,value,bean){
		println("list filter->"+name);
		for(var i=0;i<value.size();i++){
			handlers.match(value.get(i)).filter(i,value.get(i),value,listRepl);
		}
	}
})
handlers.register("map",function(value){
	var name = getClassName(value);
//	return name.indexOf("java.util") == 0 && name.indexOf("Map") > 0;
	return matchReg.map.test(name);
},{
	filter: function(name,value,bean){
		println("map filter");
		var values = value.values();
		for(var i=0;i<values.size();i++){
			handlers.match(values.get(i)).filter(name,values.get(i),value,objRepl);
		}
	}
})

handlers.register("array",function(value){
	var name = getClassName(value);
	return matchReg.array.test(name);
},{
	filter: function(name,value,bean){
//		for(var index in value){
//			var new_value = value[index];
//			handlers.match(new_value).filter(index,new_value,value,objRepl);
//		}
		for(var i=0,len=value.length;i<len;i++){
			var new_value = value[i];
			handlers.match(new_value).filter(i,new_value,value,objRepl);
		}
	}
})

//这个方法是入口方法
function filterString(bean){
	//如果是
	println("begin---------------------");
	handlers.match(bean).filter("",bean,null);
	
}

function getClassName(value){
	return String(value.getClass().name);
}

//目前的想法是这样的，因为目前发现这个有点可以用compose模式,因为在枝节点上有可能多种不同的处理方式,比如List,Map,general Object,
// 而具体到叶子节点,所有的处理方式是相同的，这样感觉会有点问题,因为一个对象的属性是动态变化的，看来用组合还不太合适，还是用一个map保存
//所有的处理器,然后每次解析一个对象的时候，都去这个map中找到合适的处理器,然后如果对象里面包含其他的对象的话,递归进行处理

function isStringObject(value){
	return  (String(value.getClass().name) == 'java.lang.String');
}
function isTjObject(value){
	return String(value.getClass().name).indexOf("com.tianji") > -1 || String(value.getClass().name).indexOf("leoner") > -1;
}
//这个用来过滤某些基本类型,比如数字类型,或者特殊类型比如class
function isTargetObject(name,value){
	return value && (typeof value === 'object') && (name != 'class');
}
